package com.yiruantong.system.service.core.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yiruantong.common.core.config.RattanConfig;
import com.yiruantong.common.core.constant.CacheNames;
import com.yiruantong.common.core.constant.UserConstants;
import com.yiruantong.common.core.domain.R;
import com.yiruantong.common.core.exception.ServiceException;
import com.yiruantong.common.core.service.ConfigService;
import com.yiruantong.common.core.utils.MapstructUtils;
import com.yiruantong.common.core.utils.SpringUtils;
import com.yiruantong.common.core.utils.StringUtils;
import com.yiruantong.common.mybatis.core.page.PageQuery;
import com.yiruantong.common.mybatis.core.page.TableDataInfo;
import com.yiruantong.common.mybatis.core.service.ServiceImplPlus;
import com.yiruantong.common.redis.utils.CacheUtils;
import com.yiruantong.system.domain.core.SysConfig;
import com.yiruantong.system.domain.core.bo.SysConfigBo;
import com.yiruantong.system.domain.core.vo.SysConfigVo;
import com.yiruantong.system.mapper.core.SysConfigMapper;
import com.yiruantong.system.service.core.ISysConfigService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 参数配置 服务层实现
 *
 * @author YiRuanTong
 */
@RequiredArgsConstructor
@Service
public class SysConfigServiceImpl extends ServiceImplPlus<SysConfigMapper, SysConfig, SysConfigVo, SysConfigBo> implements ISysConfigService, ConfigService {

  private final SysConfigMapper baseMapper;
  @Autowired
  private final RattanConfig rattanConfig;

  @Override
  public TableDataInfo<SysConfigVo> selectPageConfigList(SysConfigBo config, PageQuery pageQuery) {
    LambdaQueryWrapper<SysConfig> lqw = buildQueryWrapper(config);
    Page<SysConfigVo> page = baseMapper.selectVoPage(pageQuery.build(), lqw);
    return TableDataInfo.build(page);
  }

  /**
   * 查询参数配置信息
   *
   * @param configId 参数配置ID
   * @return 参数配置信息
   */
  @Override
  @DS("master")
  public SysConfigVo selectConfigById(Long configId) {
    return baseMapper.selectVoById(configId);
  }

  /**
   * 根据键名查询参数配置信息
   *
   * @param configKey 参数key
   * @return 参数键值
   */
  @Override
  @Cacheable(cacheNames = CacheNames.SYS_CONFIG, key = "'configVo-'.concat(#configKey)")
  public SysConfigVo selectOneByKey(String configKey) {
    SysConfig retConfig = baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>()
      .eq(SysConfig::getConfigKey, configKey));

    return MapstructUtils.convert(retConfig, SysConfigVo.class);
  }

  @Override
  public List<SysConfigVo> selectOneByKeys(List<String> configKeys) {
    if (configKeys.isEmpty()) {
      configKeys.add("-1");
    }

    LambdaQueryWrapper<SysConfig> configLambdaQueryWrapper = new LambdaQueryWrapper<SysConfig>()
      .in(SysConfig::getConfigKey, configKeys);

    return baseMapper.selectVoList(configLambdaQueryWrapper);
  }

  /**
   * 根据键名查询参数配置信息
   *
   * @param configKey 参数key
   * @return 参数键值
   */
//  @Cacheable(cacheNames = CacheNames.SYS_CONFIG, key = "#configKey")
  @Override
  public String selectConfigByKey(String configKey) {
    SysConfig retConfig = this.getOne(new LambdaQueryWrapper<SysConfig>()
      .eq(SysConfig::getConfigKey, configKey));
    if (ObjectUtil.isNotNull(retConfig)) {
      return retConfig.getConfigValue();
    }
    return StringUtils.EMPTY;
  }

  /**
   * 获取注册开关
   *
   * @return true开启，false关闭
   */
  @Override
  public boolean registerEnabled() {
    return rattanConfig.isOpenReg();
//    SysConfig retConfig = baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>()
//      .eq(SysConfig::getConfigKey, "sys.account.registerUser")
//      .eq(TenantHelper.isEnable(), SysConfig::getTenantId, tenantId));
//    if (ObjectUtil.isNull(retConfig)) {
//      return false;
//    }
//    return Convert.toBool(retConfig.getConfigValue());
  }

  /**
   * 查询参数配置列表
   *
   * @param config 参数配置信息
   * @return 参数配置集合
   */
  @Override
  public List<SysConfigVo> selectConfigList(SysConfigBo config) {
    LambdaQueryWrapper<SysConfig> lqw = buildQueryWrapper(config);
    return baseMapper.selectVoList(lqw);
  }

  private LambdaQueryWrapper<SysConfig> buildQueryWrapper(SysConfigBo bo) {
    Map<String, Object> params = bo.getParams();
    LambdaQueryWrapper<SysConfig> lqw = Wrappers.lambdaQuery();
    lqw.like(StringUtils.isNotBlank(bo.getConfigName()), SysConfig::getConfigName, bo.getConfigName());
    lqw.eq(StringUtils.isNotBlank(bo.getConfigType()), SysConfig::getConfigType, bo.getConfigType());
    lqw.like(StringUtils.isNotBlank(bo.getConfigKey()), SysConfig::getConfigKey, bo.getConfigKey());
    lqw.between(params.get("beginTime") != null && params.get("endTime") != null,
      SysConfig::getCreateTime, params.get("beginTime"), params.get("endTime"));
    lqw.orderByAsc(SysConfig::getConfigId);
    return lqw;
  }

  /**
   * 新增参数配置
   *
   * @param bo 参数配置信息
   * @return 结果
   */
  @CachePut(cacheNames = CacheNames.SYS_CONFIG, key = "#bo.configKey")
  @Override
  public String insertConfig(SysConfigBo bo) {
    SysConfig config = MapstructUtils.convert(bo, SysConfig.class);
    int row = baseMapper.insert(config);
    if (row > 0) {
      return config.getConfigValue();
    }
    throw new ServiceException("操作失败");
  }

  /**
   * 修改参数配置
   *
   * @param bo 参数配置信息
   * @return 结果
   */
  @CachePut(cacheNames = CacheNames.SYS_CONFIG, key = "#bo.configKey")
  @Override
  public String updateConfig(SysConfigBo bo) {
    int row = 0;
    SysConfig config = MapstructUtils.convert(bo, SysConfig.class);
    if (config.getConfigId() != null) {
      SysConfig temp = baseMapper.selectById(config.getConfigId());
      if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey())) {
        CacheUtils.evict(CacheNames.SYS_CONFIG, temp.getConfigKey());
      }
      row = baseMapper.updateById(config);
    } else {
      row = baseMapper.update(config, new LambdaQueryWrapper<SysConfig>()
        .eq(SysConfig::getConfigKey, config.getConfigKey()));
    }
    if (row > 0) {
      return config.getConfigValue();
    }
    throw new ServiceException("操作失败");
  }

  /**
   * 批量删除参数信息
   *
   * @param configIds 需要删除的参数ID
   */
  @Override
  public void deleteConfigByIds(Long[] configIds) {
    for (Long configId : configIds) {
      SysConfig config = baseMapper.selectById(configId);
      if (StringUtils.equals(UserConstants.YES, config.getConfigType())) {
        throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey()));
      }
      CacheUtils.evict(CacheNames.SYS_CONFIG, config.getConfigKey());
    }
    baseMapper.deleteBatchIds(Arrays.asList(configIds));
  }

  /**
   * 重置参数缓存数据
   */
  @Override
  public void resetConfigCache() {
    CacheUtils.clear(CacheNames.SYS_CONFIG);
  }

  /**
   * 校验参数键名是否唯一
   *
   * @param config 参数配置信息
   * @return 结果
   */
  @Override
  public boolean checkConfigKeyUnique(SysConfigBo config) {
    long configId = ObjectUtil.isNull(config.getConfigId()) ? -1L : config.getConfigId();
    SysConfig info = baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>().eq(SysConfig::getConfigKey, config.getConfigKey()));
    return !ObjectUtil.isNotNull(info) || info.getConfigId() == configId;
  }

  /**
   * 根据参数 key 获取参数值
   *
   * @param configKey 参数 key
   * @return 参数值
   */
  @Override
  public String getConfigValue(String configKey) {
    return SpringUtils.getAopProxy(this).selectConfigByKey(configKey);
  }

  /**
   * 根据参数 keys 获取参数值，多个值采用都好分隔
   *
   * @param configKeys 参数 keys
   * @return 参数值集合
   */
  @Override
  public List<Map<String, Object>> getConfigValues(String configKeys) {
    var strList = StringUtils.split(configKeys, ",");
    List<SysConfigVo> sysConfigVos = this.selectOneByKeys(List.of(strList));

    return sysConfigVos.stream().map(vo -> {
      Map<String, Object> map = new HashMap<>();
      if (ObjectUtil.isNotEmpty(vo)) {
        map.put("configId", vo.getConfigId());
        map.put("configKey", vo.getConfigKey());
        map.put("configValue", vo.getConfigValue());
      }
      return map;
    }).filter(f -> ObjectUtil.isNotEmpty(f.get("configValue"))).toList();
  }

  @Override
  public boolean getConfigBool(String configKey) {
    String val = getConfigValue(configKey);
    return "1".equals(val);
  }


  /**
   * 保存参数集合
   *
   * @param map 参数
   * @return 参数值集合
   */
  @Override
  public R<List<SysConfigVo>> saveParams(Map<String, Object> map) {
    List<SysConfig> valueList = Convert.toList(SysConfig.class, map.get("valueList"));
    List<SysConfigVo> sysConfigVos = this.selectOneByKeys(valueList.stream().map(SysConfig::getConfigKey).toList());

    if (valueList.stream().anyMatch(a -> StringUtils.isEmpty(a.getConfigKey()))) {
      throw new ServiceException("参数key不能为空");
    }
    for (var config : valueList) {
      if (sysConfigVos.stream().anyMatch(m -> StringUtils.equals(m.getConfigKey(), config.getConfigKey()))) {
        this.updateById(config);
      } else {
        config.setConfigId(null);
        this.save(config);
      }
    }

    CacheUtils.clear(CacheNames.SYS_CONFIG); // 清除缓存
    sysConfigVos = MapstructUtils.convert(valueList, SysConfigVo.class);

    return R.ok("保存成功", sysConfigVos);
  }
}
